package com.example.cp14.practice;


import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.UUID;
import java.util.concurrent.atomic.LongAdder;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * 第一，如果需要读写字符流，那么需要确保文件中字符的字符集和字符流的字符集是一致的，否则可能产生乱码。
 * 第二，使用 Files 类的一些流式处理操作，注意使用 try-with-resources 包装 Stream，确保底层文件资源可以释放，避免产生 too many open files 的问题。
 * 第三，进行文件字节流操作的时候，一般情况下不考虑进行逐字节操作，使用缓冲区进行批量读写减少 IO 次数，性能会好很多。一般可以考虑直接使用缓冲输入输出流 BufferedXXXStream，追求极限性能的话可以考虑使用 FileChannel 进行流转发。
 */
public class Test {

   // 使用FIles静态方法读取文件需要手动释放资源，否则会出现to many files 错误
    public void test() throws IOException {
        Files.write(Paths.get("test.txt"), IntStream.rangeClosed(1,10).
                mapToObj(i-> UUID.randomUUID().toString()).collect(Collectors.toList()));

        LongAdder la = new LongAdder();
        IntStream.rangeClosed(1,1000000).forEach(i->{
            try {
                Files.lines(Paths.get("test.txt")).forEach(j->la.increment());
            }catch (IOException e){
                e.printStackTrace();
            }
        });
    }

    // 对于too many files 错误采用try-resource 即可
    public void test2(){
        LongAdder la = new LongAdder();
        IntStream.rangeClosed(1,1000000).forEach(i->{
            try (Stream<String> lines = Files.lines(Paths.get("test.txt"))){
                lines.forEach(j->{
                    la.increment();
                });
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * 对于文件读取并写入到一个新的文件中不同写法耗时，建议使用缓冲区，避免一个字节读取并且写入，如果使用BufferedInputStream，
     * 也建议添加一个字节缓冲区提高效率
     * @throws IOException
     */

    //使用BufferedInputStream和BufferedOutputStream
    private static void bufferedStreamByteOperation() throws IOException {
        try (BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("src.txt"));
             BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("dest.txt"))) {
            int i;
            while ((i = bufferedInputStream.read()) != -1) {
                bufferedOutputStream.write(i);
            }
        }
    }
    //额外使用一个8KB缓冲，再使用BufferedInputStream和BufferedOutputStream
    private static void bufferedStreamBufferOperation() throws IOException {
        try (BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("src.txt"));
             BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("dest.txt"))) {
            byte[] buffer = new byte[8192];
            int len;
            while ((len = bufferedInputStream.read(buffer)) != -1) {
                bufferedOutputStream.write(buffer, 0, len);
            }
        }
    }
    //直接使用FileInputStream和FileOutputStream，再使用一个8KB的缓冲
    private static void largerBufferOperation() throws IOException {
        try (FileInputStream fileInputStream = new FileInputStream("src.txt");
             FileOutputStream fileOutputStream = new FileOutputStream("dest.txt")) {
            byte[] buffer = new byte[8192];
            int len;
            while ((len = fileInputStream.read(buffer)) != -1) {
                fileOutputStream.write(buffer, 0, len);
            }
        }
    }
}
